<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  

  
  <title>RecastCrowd笔记 | Abel&#39;Blog</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="description" content="开始阅读一下recast-crowds相关知识，这个功能是避免怪物在跑动的时候，挤在一块。先从数据结构开始了解。 RVO视频参考 每个agent都认为其他的agent都会移动； agent在接近其他agent的时候，速度会变慢，甚至能停止； 当拥挤的时候，将会先尝试自己指向最近的寻路点连线向量$\vec{a}$，是否存在碰撞； 如果有碰撞，先减速，将$\vec{a}$向量±45°做短距离移动； 源">
<meta property="og:type" content="article">
<meta property="og:title" content="RecastCrowd笔记">
<meta property="og:url" content="http://example.com/2021/07/28/2021/2021-03-16-recast.crowd%E7%AC%94%E8%AE%B0/index.html">
<meta property="og:site_name" content="Abel&#39;Blog">
<meta property="og:description" content="开始阅读一下recast-crowds相关知识，这个功能是避免怪物在跑动的时候，挤在一块。先从数据结构开始了解。 RVO视频参考 每个agent都认为其他的agent都会移动； agent在接近其他agent的时候，速度会变慢，甚至能停止； 当拥挤的时候，将会先尝试自己指向最近的寻路点连线向量$\vec{a}$，是否存在碰撞； 如果有碰撞，先减速，将$\vec{a}$向量±45°做短距离移动； 源">
<meta property="og:locale" content="en_US">
<meta property="article:published_time" content="2021-07-28T03:33:01.247Z">
<meta property="article:modified_time" content="2021-05-05T10:06:37.899Z">
<meta property="article:author" content="Abel Sean">
<meta property="article:tag" content="Game">
<meta property="article:tag" content="recast">
<meta name="twitter:card" content="summary">
  
    <link rel="alternate" href="/atom.xml" title="Abel&#39;Blog" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.png">
  
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  
<link rel="stylesheet" href="/css/style.css">

<meta name="generator" content="Hexo 5.4.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/" id="logo">Abel&#39;Blog</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/">Home</a>
        
          <a class="main-nav-link" href="/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="http://example.com"></form>
      </div>
    </div>
  </div>
</header>
      <div class="outer">
        <section id="main"><article id="post-2021/2021-03-16-recast.crowd笔记" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2021/07/28/2021/2021-03-16-recast.crowd%E7%AC%94%E8%AE%B0/" class="article-date">
  <time datetime="2021-07-28T03:33:01.247Z" itemprop="datePublished">2021-07-28</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 class="article-title" itemprop="name">
      RecastCrowd笔记
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <p>开始阅读一下recast-crowds相关知识，这个功能是避免怪物在跑动的时候，挤在一块。先从数据结构开始了解。</p>
<p><a target="_blank" rel="noopener" href="http://gamma.cs.unc.edu/RVO/icra2008.wmv">RVO视频参考</a></p>
<p>每个agent都认为其他的agent都会移动；</p>
<p>agent在接近其他agent的时候，速度会变慢，甚至能停止；</p>
<p>当拥挤的时候，将会先尝试自己指向最近的寻路点连线向量$\vec{a}$，是否存在碰撞；</p>
<p>如果有碰撞，先减速，将$\vec{a}$向量±45°做短距离移动；</p>
<p>源码中通过@ingroup来做分类。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/// @ingroup crowd</span></span><br></pre></td></tr></table></figure>

<p>具体工程：</p>
<p>DetourCrowd</p>
<h1 id="初步阅读"><a href="#初步阅读" class="headerlink" title="初步阅读"></a>初步阅读</h1><h2 id="概念罗列"><a href="#概念罗列" class="headerlink" title="概念罗列"></a>概念罗列</h2><h3 id="名词解释"><a href="#名词解释" class="headerlink" title="名词解释"></a>名词解释</h3><p>里面使用了一些概念：</p>
<table>
<thead>
<tr>
<th align="left">单词</th>
<th align="left">释义</th>
<th align="left">备注</th>
</tr>
</thead>
<tbody><tr>
<td align="left">bound</td>
<td align="left">限制</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">Boundary</td>
<td align="left">边界</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">convex</td>
<td align="left">凸多边形</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">volume</td>
<td align="left">卷，大量</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">avoidance</td>
<td align="left">避免，逃避；废止</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">Segment</td>
<td align="left">段，部分</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">Poly</td>
<td align="left">多边形</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">Corner</td>
<td align="left">角落</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">Topology</td>
<td align="left">拓扑</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">purge</td>
<td align="left">清理</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">steering</td>
<td align="left">导航</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">corridor</td>
<td align="left">走廊</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">segment</td>
<td align="left">段</td>
<td align="left"></td>
</tr>
</tbody></table>
<h2 id="文件清单"><a href="#文件清单" class="headerlink" title="文件清单"></a>文件清单</h2><h3 id="DetourCrowd-文件"><a href="#DetourCrowd-文件" class="headerlink" title="DetourCrowd 文件"></a>DetourCrowd 文件</h3><p>限定：</p>
<p>为转向决定，提供的最大的相邻对象</p>
<h4 id="class-dtCrowd"><a href="#class-dtCrowd" class="headerlink" title="class dtCrowd"></a>class dtCrowd</h4><p>对外提供对于一组 dtCrowdAgent 管理的类。</p>
<p>成员</p>
<figure class="highlight hpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> m_maxAgents;<span class="comment">// 最大代理数目</span></span><br><span class="line">dtCrowdAgent* m_agents;<span class="comment">// 当前持有的代理</span></span><br><span class="line">dtCrowdAgent** m_activeAgents;<span class="comment">// 激活的代理</span></span><br><span class="line">dtCrowdAgentAnimation* m_agentAnims;<span class="comment">// 代理动画</span></span><br><span class="line"></span><br><span class="line">dtPathQueue m_pathq;<span class="comment">// 寻路队列</span></span><br><span class="line"></span><br><span class="line">dtObstacleAvoidanceParams m_obstacleQueryParams[DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS];<span class="comment">//阻挡寻路参数</span></span><br><span class="line">dtObstacleAvoidanceQuery* m_obstacleQuery;<span class="comment">//阻挡寻路</span></span><br><span class="line"></span><br><span class="line">dtProximityGrid* m_grid;<span class="comment">// 近似单元格</span></span><br><span class="line"></span><br><span class="line">dtPolyRef* m_pathResult;<span class="comment">// 寻路面片集合</span></span><br><span class="line"><span class="keyword">int</span> m_maxPathResult;<span class="comment">// 最大面片数目</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">float</span> m_agentPlacementHalfExtents[<span class="number">3</span>];</span><br><span class="line"></span><br><span class="line">dtQueryFilter m_filters[DT_CROWD_MAX_QUERY_FILTER_TYPE];<span class="comment">// 查询过滤器</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">float</span> m_maxAgentRadius;<span class="comment">// 最大的代理对象的半径</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> m_velocitySampleCount;<span class="comment">// 速度样本数</span></span><br><span class="line"></span><br><span class="line">dtNavMeshQuery* m_navquery;<span class="comment">// 导航寻路对象</span></span><br></pre></td></tr></table></figure>

<p>私有函数：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 更新拓扑优化</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">updateTopologyOptimization</span><span class="params">(dtCrowdAgent** agents, <span class="keyword">const</span> <span class="keyword">int</span> nagents, <span class="keyword">const</span> <span class="keyword">float</span> dt)</span></span>;</span><br><span class="line"><span class="comment">// 更新移动请求</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">updateMoveRequest</span><span class="params">(<span class="keyword">const</span> <span class="keyword">float</span> dt)</span></span>;</span><br><span class="line"><span class="comment">// 检查路径的有效性</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">checkPathValidity</span><span class="params">(dtCrowdAgent** agents, <span class="keyword">const</span> <span class="keyword">int</span> nagents, <span class="keyword">const</span> <span class="keyword">float</span> dt)</span></span>;</span><br><span class="line"><span class="comment">// 获取代理的index</span></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="keyword">int</span> <span class="title">getAgentIndex</span><span class="params">(<span class="keyword">const</span> dtCrowdAgent* agent)</span> <span class="keyword">const</span>  </span>&#123; <span class="keyword">return</span> (<span class="keyword">int</span>)(agent - m_agents); &#125;</span><br><span class="line"><span class="comment">// 请求重新设定移动目标位置</span></span><br><span class="line"><span class="function"><span class="keyword">bool</span> <span class="title">requestMoveTargetReplan</span><span class="params">(<span class="keyword">const</span> <span class="keyword">int</span> idx, dtPolyRef ref, <span class="keyword">const</span> <span class="keyword">float</span>* pos)</span></span>;</span><br><span class="line"><span class="comment">// 清理</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">purge</span><span class="params">()</span></span>;</span><br></pre></td></tr></table></figure>

<p>公用函数：</p>
<figure class="highlight hpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 初始化crowd对象，新建一批agent，设置agent的半径，设置寻路对象；</span></span><br><span class="line"><span class="function"><span class="keyword">bool</span> <span class="title">init</span><span class="params">(<span class="keyword">const</span> <span class="keyword">int</span> maxAgents, <span class="keyword">const</span> <span class="keyword">float</span> maxAgentRadius, dtNavMesh* nav)</span></span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<h4 id="struct-dtCrowdAgent"><a href="#struct-dtCrowdAgent" class="headerlink" title="struct dtCrowdAgent"></a>struct dtCrowdAgent</h4><p>被 dtCrowd 管理的单个 agent 对象</p>
<figure class="highlight hpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">/// True if the agent is active, false if the agent is in an unused slot in the agent pool.</span></span><br><span class="line"><span class="keyword">bool</span> active;</span><br><span class="line"></span><br><span class="line"><span class="comment">/// The type of mesh polygon the agent is traversing. (See: #CrowdAgentState)</span></span><br><span class="line"><span class="keyword">unsigned</span> <span class="keyword">char</span> state;</span><br><span class="line"></span><br><span class="line"><span class="comment">/// True if the agent has valid path (targetState == DT_CROWDAGENT_TARGET_VALID) and the path does not lead to the requested position, else false.</span></span><br><span class="line"><span class="keyword">bool</span> partial;</span><br><span class="line"></span><br><span class="line"><span class="comment">/// The path corridor the agent is using.</span></span><br><span class="line">dtPathCorridor corridor;</span><br><span class="line"></span><br><span class="line"><span class="comment">/// The local boundary data for the agent.</span></span><br><span class="line">dtLocalBoundary boundary;</span><br><span class="line"></span><br><span class="line"><span class="comment">/// Time since the agent&#x27;s path corridor was optimized.</span></span><br><span class="line"><span class="keyword">float</span> topologyOptTime;</span><br><span class="line"></span><br><span class="line"><span class="comment">/// The known neighbors of the agent.</span></span><br><span class="line">dtCrowdNeighbour neis[DT_CROWDAGENT_MAX_NEIGHBOURS];</span><br><span class="line"></span><br><span class="line"><span class="comment">/// The number of neighbors.</span></span><br><span class="line"><span class="keyword">int</span> nneis;</span><br><span class="line"></span><br><span class="line"><span class="comment">/// The desired speed.</span></span><br><span class="line"><span class="keyword">float</span> desiredSpeed;</span><br><span class="line"></span><br><span class="line"><span class="keyword">float</span> npos[<span class="number">3</span>];    <span class="comment">///&lt; The current agent position. [(x, y, z)]</span></span><br><span class="line"><span class="keyword">float</span> disp[<span class="number">3</span>];    <span class="comment">///&lt; A temporary value used to accumulate agent displacement during iterative collision resolution. [(x, y, z)]</span></span><br><span class="line"><span class="keyword">float</span> dvel[<span class="number">3</span>];    <span class="comment">///&lt; The desired velocity of the agent. Based on the current path, calculated from scratch each frame. [(x, y, z)]</span></span><br><span class="line"><span class="keyword">float</span> nvel[<span class="number">3</span>];    <span class="comment">///&lt; The desired velocity adjusted by obstacle avoidance, calculated from scratch each frame. [(x, y, z)]</span></span><br><span class="line"><span class="keyword">float</span> vel[<span class="number">3</span>];    <span class="comment">///&lt; The actual velocity of the agent. The change from nvel -&gt; vel is constrained by max acceleration. [(x, y, z)]</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/// The agent&#x27;s configuration parameters.</span></span><br><span class="line">dtCrowdAgentParams params;</span><br><span class="line"></span><br><span class="line"><span class="comment">/// The local path corridor corners for the agent. (Staight path.) [(x, y, z) * #ncorners]</span></span><br><span class="line"><span class="keyword">float</span> cornerVerts[DT_CROWDAGENT_MAX_CORNERS*<span class="number">3</span>];</span><br><span class="line"></span><br><span class="line"><span class="comment">/// The local path corridor corner flags. (See: #dtStraightPathFlags) [(flags) * #ncorners]</span></span><br><span class="line"><span class="keyword">unsigned</span> <span class="keyword">char</span> cornerFlags[DT_CROWDAGENT_MAX_CORNERS];</span><br><span class="line"></span><br><span class="line"><span class="comment">/// The reference id of the polygon being entered at the corner. [(polyRef) * #ncorners]</span></span><br><span class="line">dtPolyRef cornerPolys[DT_CROWDAGENT_MAX_CORNERS];</span><br><span class="line"></span><br><span class="line"><span class="comment">/// The number of corners.</span></span><br><span class="line"><span class="keyword">int</span> ncorners;</span><br><span class="line"></span><br><span class="line"><span class="keyword">unsigned</span> <span class="keyword">char</span> targetState;      <span class="comment">///&lt; State of the movement request.</span></span><br><span class="line"><span class="comment">// enum MoveRequestState</span></span><br><span class="line"><span class="comment">// &#123;</span></span><br><span class="line"><span class="comment">//  DT_CROWDAGENT_TARGET_NONE = 0,</span></span><br><span class="line"><span class="comment">//  DT_CROWDAGENT_TARGET_FAILED,</span></span><br><span class="line"><span class="comment">//  DT_CROWDAGENT_TARGET_VALID,</span></span><br><span class="line"><span class="comment">//  DT_CROWDAGENT_TARGET_REQUESTING,</span></span><br><span class="line"><span class="comment">//  DT_CROWDAGENT_TARGET_WAITING_FOR_QUEUE,</span></span><br><span class="line"><span class="comment">//  DT_CROWDAGENT_TARGET_WAITING_FOR_PATH,</span></span><br><span class="line"><span class="comment">//  DT_CROWDAGENT_TARGET_VELOCITY,</span></span><br><span class="line"><span class="comment">//&#125;;</span></span><br><span class="line">dtPolyRef targetRef;        <span class="comment">///&lt; Target polyref of the movement request.</span></span><br><span class="line"><span class="keyword">float</span> targetPos[<span class="number">3</span>];          <span class="comment">///&lt; Target position of the movement request (or velocity in case of DT_CROWDAGENT_TARGET_VELOCITY).</span></span><br><span class="line">dtPathQueueRef targetPathqRef;    <span class="comment">///&lt; Path finder ref.</span></span><br><span class="line"><span class="keyword">bool</span> targetReplan;          <span class="comment">///&lt; Flag indicating that the current path is being replanned.</span></span><br><span class="line"><span class="keyword">float</span> targetReplanTime;        <span class="comment">/// &lt;Time since the agent&#x27;s target was replanned.</span></span><br></pre></td></tr></table></figure>

<h4 id="struct-dtCrowdAgentParams"><a href="#struct-dtCrowdAgentParams" class="headerlink" title="struct dtCrowdAgentParams"></a>struct dtCrowdAgentParams</h4><p>dtCrowdAgent 的配置参数。</p>
<figure class="highlight hpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/// Configuration parameters for a crowd agent.</span></span><br><span class="line"><span class="comment">/// @ingroup crowd</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">dtCrowdAgentParams</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">  <span class="keyword">float</span> radius;            <span class="comment">///&lt; Agent radius. [Limit: &gt;= 0]</span></span><br><span class="line">  <span class="keyword">float</span> height;            <span class="comment">///&lt; Agent height. [Limit: &gt; 0]</span></span><br><span class="line">  <span class="keyword">float</span> maxAcceleration;        <span class="comment">///&lt; Maximum allowed acceleration. [Limit: &gt;= 0]</span></span><br><span class="line">  <span class="keyword">float</span> maxSpeed;            <span class="comment">///&lt; Maximum allowed speed. [Limit: &gt;= 0]</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">/// Defines how close a collision element must be before it is considered for steering behaviors. [Limits: &gt; 0]</span></span><br><span class="line">  <span class="keyword">float</span> collisionQueryRange;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">float</span> pathOptimizationRange;    <span class="comment">///&lt; The path visibility optimization range. [Limit: &gt; 0]</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">/// How aggresive the agent manager should be at avoiding collisions with this agent. [Limit: &gt;= 0]</span></span><br><span class="line">  <span class="keyword">float</span> separationWeight;</span><br><span class="line"></span><br><span class="line">  <span class="comment">/// Flags that impact steering behavior. (See: #UpdateFlags)</span></span><br><span class="line">  <span class="keyword">unsigned</span> <span class="keyword">char</span> updateFlags;</span><br><span class="line"></span><br><span class="line">  <span class="comment">/// The index of the avoidance configuration to use for the agent. </span></span><br><span class="line">  <span class="comment">/// [Limits: 0 &lt;= value &lt;= #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS]</span></span><br><span class="line">  <span class="keyword">unsigned</span> <span class="keyword">char</span> obstacleAvoidanceType;  </span><br><span class="line"></span><br><span class="line">  <span class="comment">/// The index of the query filter used by this agent.</span></span><br><span class="line">  <span class="keyword">unsigned</span> <span class="keyword">char</span> queryFilterType;</span><br><span class="line"></span><br><span class="line">  <span class="comment">/// User defined data attached to the agent.</span></span><br><span class="line">  <span class="keyword">void</span>* userData;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h4 id="struct-dtCrowdNeighbour"><a href="#struct-dtCrowdNeighbour" class="headerlink" title="struct dtCrowdNeighbour"></a>struct dtCrowdNeighbour</h4><p>提供 neighbor 数据给 agents 管理。</p>
<p>idx neighor 在 crowd 的index编号。<br>dist agent neighbor 的距离。</p>
<h4 id="enum-CrowdAgentState"><a href="#enum-CrowdAgentState" class="headerlink" title="enum CrowdAgentState"></a>enum CrowdAgentState</h4><p>/// The type of navigation mesh polygon the agent is currently traversing.<br>/// @ingroup crowd<br>enum CrowdAgentState<br>{<br>    DT_CROWDAGENT_STATE_INVALID,        ///&lt; The agent is not in a valid state.<br>    DT_CROWDAGENT_STATE_WALKING,        ///&lt; The agent is traversing a normal navigation mesh polygon.<br>    DT_CROWDAGENT_STATE_OFFMESH,        ///&lt; The agent is traversing an off-mesh connection.<br>};</p>
<h4 id="enum-MoveRequestState"><a href="#enum-MoveRequestState" class="headerlink" title="enum MoveRequestState"></a>enum MoveRequestState</h4><p>enum MoveRequestState<br>{<br>    DT_CROWDAGENT_TARGET_NONE = 0,<br>    DT_CROWDAGENT_TARGET_FAILED,<br>    DT_CROWDAGENT_TARGET_VALID,<br>    DT_CROWDAGENT_TARGET_REQUESTING,<br>    DT_CROWDAGENT_TARGET_WAITING_FOR_QUEUE,<br>    DT_CROWDAGENT_TARGET_WAITING_FOR_PATH,<br>    DT_CROWDAGENT_TARGET_VELOCITY,<br>};</p>
<h3 id="DetourLocalBoundary-文件"><a href="#DetourLocalBoundary-文件" class="headerlink" title="DetourLocalBoundary 文件"></a>DetourLocalBoundary 文件</h3><h3 id="DetourObstacleAvoidance-文件"><a href="#DetourObstacleAvoidance-文件" class="headerlink" title="DetourObstacleAvoidance 文件"></a>DetourObstacleAvoidance 文件</h3><h4 id="struct-dtObstacleAvoidanceParams"><a href="#struct-dtObstacleAvoidanceParams" class="headerlink" title="struct dtObstacleAvoidanceParams"></a>struct dtObstacleAvoidanceParams</h4><p>成员：</p>
<figure class="highlight hpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">float</span> velBias;<span class="comment">// 运动偏向</span></span><br><span class="line"><span class="keyword">float</span> weightDesVel;<span class="comment">// </span></span><br><span class="line"><span class="keyword">float</span> weightCurVel;</span><br><span class="line"><span class="keyword">float</span> weightSide;</span><br><span class="line"><span class="keyword">float</span> weightToi;<span class="comment">// </span></span><br><span class="line"><span class="keyword">float</span> horizTime;<span class="comment">// 水平时间</span></span><br><span class="line"><span class="keyword">unsigned</span> <span class="keyword">char</span> gridSize;  <span class="comment">///&lt; grid</span></span><br><span class="line"><span class="keyword">unsigned</span> <span class="keyword">char</span> adaptiveDivs;  <span class="comment">///&lt; adaptive</span></span><br><span class="line"><span class="keyword">unsigned</span> <span class="keyword">char</span> adaptiveRings;  <span class="comment">///&lt; adaptive</span></span><br><span class="line"><span class="keyword">unsigned</span> <span class="keyword">char</span> adaptiveDepth;  <span class="comment">///&lt; adaptive</span></span><br></pre></td></tr></table></figure>

<h3 id="DetourPathCorridor-文件"><a href="#DetourPathCorridor-文件" class="headerlink" title="DetourPathCorridor 文件"></a>DetourPathCorridor 文件</h3><h3 id="DetourPathQueue-文件"><a href="#DetourPathQueue-文件" class="headerlink" title="DetourPathQueue 文件"></a>DetourPathQueue 文件</h3><h4 id="class-dtPathQueue"><a href="#class-dtPathQueue" class="headerlink" title="class dtPathQueue"></a>class dtPathQueue</h4><p>寻路队列；</p>
<h4 id="struct-PathQuery"><a href="#struct-PathQuery" class="headerlink" title="struct PathQuery"></a>struct PathQuery</h4><h3 id="DetourProximityGrid-文件"><a href="#DetourProximityGrid-文件" class="headerlink" title="DetourProximityGrid 文件"></a>DetourProximityGrid 文件</h3><h2 id="主流程梳理"><a href="#主流程梳理" class="headerlink" title="主流程梳理"></a>主流程梳理</h2><h3 id="dwCrowd-update"><a href="#dwCrowd-update" class="headerlink" title="dwCrowd::update"></a>dwCrowd::update</h3><p>细读update函数：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 每一帧都在调用的函数。</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">dtCrowd::update</span><span class="params">(<span class="keyword">const</span> <span class="keyword">float</span> dt, dtCrowdAgentDebugInfo* debug)</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">  <span class="comment">// 先将本组全部的 agent 获取出来。</span></span></span><br><span class="line"><span class="function">  <span class="keyword">int</span> <span class="title">dtCrowd::getActiveAgents</span><span class="params">(dtCrowdAgent** agents, <span class="keyword">const</span> <span class="keyword">int</span> maxAgents)</span></span>&#123;...&#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 检查全部的 agent 还有合法的寻路路点；</span></span><br><span class="line">  <span class="function"><span class="keyword">void</span> <span class="title">dtCrowd::checkPathValidity</span><span class="params">(dtCrowdAgent** agents, <span class="keyword">const</span> <span class="keyword">int</span> nagents, <span class="keyword">const</span> <span class="keyword">float</span> dt)</span></span>&#123;...&#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 更新同步移动请求和寻路对象</span></span><br><span class="line">  <span class="function"><span class="keyword">void</span> <span class="title">dtCrowd::updateMoveRequest</span><span class="params">(<span class="keyword">const</span> <span class="keyword">float</span> )</span></span>&#123;...&#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 优化拓扑</span></span><br><span class="line">  <span class="function"><span class="keyword">void</span> <span class="title">dtCrowd::updateTopologyOptimization</span><span class="params">(dtCrowdAgent** agents, <span class="keyword">const</span> <span class="keyword">int</span> nagents, <span class="keyword">const</span> <span class="keyword">float</span> dt)</span></span>&#123;...&#125;</span><br><span class="line">  </span><br><span class="line">  <span class="comment">// 将agents注册到 proximity grid </span></span><br><span class="line">  <span class="comment">// 其实就是获取当前的agent对象的pos，radius，计算一个正方形，添加到 proximity grid 中。</span></span><br><span class="line">  <span class="comment">// 可以理解成栅格化；</span></span><br><span class="line">    dtProximityGrid::addItem</span><br><span class="line">  </span><br><span class="line">  <span class="comment">// 获取全部 agent 靠近的 navmesh segments，其实也会将 agent 的 neighbours 都重新生成</span></span><br><span class="line">  <span class="comment">// Get nearby navmesh segments and agents to collide with.</span></span><br><span class="line">    <span class="comment">// 检查 agent 状态需要是 DT_CROWDAGENT_STATE_WALKING</span></span><br><span class="line">    <span class="keyword">if</span> (ag-&gt;state != DT_CROWDAGENT_STATE_WALKING)</span><br><span class="line">    <span class="comment">// 当 agent collision boundary 无效了或者确定距离通过了，将更新 collision boundary。</span></span><br><span class="line">    <span class="comment">// 先计算一个标准量，读取 agent collisionQueryRange</span></span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">float</span> updateThr = ag-&gt;params.collisionQueryRange*<span class="number">0.25f</span>;</span><br><span class="line">    <span class="comment">// 计算自己位置是否超出了 boundary 的区间</span></span><br><span class="line">    <span class="built_in">dtVdist2DSqr</span>(ag-&gt;npos, ag-&gt;boundary.<span class="built_in">getCenter</span>()) &gt; <span class="built_in">dtSqr</span>(updateThr)</span><br><span class="line">    <span class="comment">// 检查 boundary 是否还合法</span></span><br><span class="line">    !ag-&gt;boundary.<span class="built_in">isValid</span>(m_navquery, &amp;m_filters[ag-&gt;params.queryFilterType])</span><br><span class="line">      <span class="comment">// 检测 Boundary 是否合法</span></span><br><span class="line">      <span class="function"><span class="keyword">bool</span> <span class="title">dtLocalBoundary::isValid</span><span class="params">(dtNavMeshQuery* navquery, <span class="keyword">const</span> dtQueryFilter* filter)</span></span></span><br><span class="line"><span class="function">      <span class="comment">// 更新 boundary.update</span></span></span><br><span class="line"><span class="function">      ag-&gt;boundary.update</span></span><br><span class="line"><span class="function">    <span class="comment">// 获取 agent 的 neighbour agents</span></span></span><br><span class="line"><span class="function">    <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getNeighbours</span><span class="params">()</span></span></span><br><span class="line"><span class="function">      <span class="comment">// 从 dtProximityGrid::queryItems()</span></span></span><br><span class="line"><span class="function">      <span class="comment">// 通过近似格子获取附近的agents对象。</span></span></span><br><span class="line"><span class="function">      <span class="comment">// 循环全部的附近 agent</span></span></span><br><span class="line"><span class="function">      <span class="comment">// 检查高度是否相差太大</span></span></span><br><span class="line"><span class="function">      <span class="comment">// 检查距离是否太远</span></span></span><br><span class="line"><span class="function">      <span class="comment">// static int addNeighbour()</span></span></span><br><span class="line"><span class="function">      <span class="comment">// 写入 agent.neis 数组中</span></span></span><br><span class="line"><span class="function">  <span class="comment">// 循环全部的 agent 可以到 corner</span></span></span><br><span class="line"><span class="function">  <span class="comment">// Find next corner to steer to.</span></span></span><br><span class="line"><span class="function">    <span class="comment">// 检查 agent.state 是否 DT_CROWDAGENT_STATE_WALKING</span></span></span><br><span class="line"><span class="function">    <span class="comment">// 检查 agent.targetState 为 DT_CROWDAGENT_TARGET_NONE DT_CROWDAGENT_TARGET_VELOCITY</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">    <span class="comment">// int dtPathCorridor::findCorners</span></span></span><br><span class="line"><span class="function">    <span class="comment">// 类似 dtNavMeshQuery::findStraightPath 函数</span></span></span><br><span class="line"><span class="function">    <span class="keyword">int</span> <span class="title">findCorners</span><span class="params">(<span class="keyword">float</span>* cornerVerts, <span class="keyword">unsigned</span> <span class="keyword">char</span>* cornerFlags, dtPolyRef* cornerPolys, <span class="keyword">const</span> <span class="keyword">int</span> maxCorners, dtNavMeshQuery* navquery, <span class="keyword">const</span> dtQueryFilter* filter)</span></span></span><br><span class="line"><span class="function">    <span class="comment">// 最多收集4步</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">  <span class="comment">// 根据配置，检查是否开启了优化，将会直接将下一个 corner 裁剪掉。</span></span></span><br><span class="line"><span class="function">  <span class="comment">// Find next corner to steer to.</span></span></span><br><span class="line"><span class="function">    <span class="keyword">void</span> <span class="title">optimizePathVisibility</span><span class="params">(<span class="keyword">const</span> <span class="keyword">float</span>* next, <span class="keyword">const</span> <span class="keyword">float</span> pathOptimizationRange, dtNavMeshQuery* navquery, <span class="keyword">const</span> dtQueryFilter* filter)</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">    <span class="comment">// 后续将会为输出日志，拷贝一些数据。</span></span></span><br><span class="line"><span class="function">    <span class="comment">// 将导航路径开始位置，结束位置写入debug对象中。</span></span></span><br><span class="line"><span class="function">  </span></span><br><span class="line"><span class="function">  <span class="comment">// 循环全部的 agent 触发跳跃点连接，直接将 mesh 连接到一块。</span></span></span><br><span class="line"><span class="function">  <span class="comment">// Trigger off-mesh connections (depends on corners).</span></span></span><br><span class="line"><span class="function">    <span class="comment">// 触发器的 2.25f 范围</span></span></span><br><span class="line"><span class="function">    <span class="keyword">bool</span> <span class="title">overOffmeshConnection</span><span class="params">(<span class="keyword">const</span> dtCrowdAgent* ag, <span class="keyword">const</span> <span class="keyword">float</span> radius)</span></span></span><br><span class="line"><span class="function">      <span class="comment">// 跳跃点</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">  <span class="comment">// 计算转向</span></span></span><br><span class="line"><span class="function">  <span class="comment">// Calculate steering.</span></span></span><br><span class="line"><span class="function">    <span class="comment">// 如果无需转向就全速前进</span></span></span><br><span class="line"><span class="function">    <span class="title">if</span> <span class="params">(ag-&gt;targetState == DT_CROWDAGENT_TARGET_VELOCITY)</span></span></span><br><span class="line"><span class="function">    <span class="comment">// 否则</span></span></span><br><span class="line"><span class="function">      <span class="comment">// 检查是否开启了 Anticipate Turns ，预判转弯</span></span></span><br><span class="line"><span class="function">        <span class="comment">// 进行更加圆滑的转弯</span></span></span><br><span class="line"><span class="function">        <span class="keyword">void</span> <span class="title">calcSmoothSteerDirection</span><span class="params">(<span class="keyword">const</span> dtCrowdAgent* ag, <span class="keyword">float</span>* dir)</span></span></span><br><span class="line"><span class="function">      <span class="comment">// 否则</span></span></span><br><span class="line"><span class="function">        <span class="comment">// 直接转弯</span></span></span><br><span class="line"><span class="function">        <span class="keyword">void</span> <span class="title">calcStraightSteerDirection</span><span class="params">(<span class="keyword">const</span> dtCrowdAgent* ag, <span class="keyword">float</span>* dir)</span></span></span><br><span class="line"><span class="function">      <span class="comment">// 如果快到终点（2倍于自己的半径）的时候，将会让 agent 减速；</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">  <span class="comment">// 计算速度</span></span></span><br><span class="line"><span class="function">  <span class="comment">// Velocity planning.	</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">  <span class="comment">// 循环全部的 agent 计算转向。</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"></span></span><br></pre></td></tr></table></figure>

<h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>多阅读别人的代码，学会如何程序如何去做框架。</p>
<h1 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h1><ul>
<li>[1] <a target="_blank" rel="noopener" href="https://blog.csdn.net/hjssss/category_8638342.html">Recast源码</a></li>
<li>[2] <a target="_blank" rel="noopener" href="https://www.pianshen.com/article/8639807482/">dtCrowd::update源码阅读</a></li>
<li>[3] <a target="_blank" rel="noopener" href="http://gamma.cs.unc.edu/RVO/">RVO障碍物规避算法</a></li>
</ul>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://example.com/2021/07/28/2021/2021-03-16-recast.crowd%E7%AC%94%E8%AE%B0/" data-id="ckrn3an7d001l20xwczq35qgh" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Game/" rel="tag">Game</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/recast/" rel="tag">recast</a></li></ul>

    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/2021/07/28/2021/2021-03-19-python-log/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          python日志加工
        
      </div>
    </a>
  
  
    <a href="/2021/07/28/2021/2021-03-15-BEHAVIOR3EDITOR%E5%AD%A6%E4%B9%A0/" id="article-nav-older" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Older</strong>
      <div class="article-nav-title">Behavior3Editor批量导出改造</div>
    </a>
  
</nav>

  
</article>

</section>
        
          <aside id="sidebar">
  
    

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/tags/3D/" rel="tag">3D</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/AI/" rel="tag">AI</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/C/" rel="tag">C++</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Game/" rel="tag">Game</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Go/" rel="tag">Go</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Linux/" rel="tag">Linux</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Math/" rel="tag">Math</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Server/" rel="tag">Server</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Unreal-Engine4/" rel="tag">Unreal Engine4</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/git/" rel="tag">git</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/golang/" rel="tag">golang</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/guitar/" rel="tag">guitar</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/node-js/" rel="tag">node.js</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/protobuf/" rel="tag">protobuf</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/python/" rel="tag">python</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/recast/" rel="tag">recast</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/redis/" rel="tag">redis</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/type/" rel="tag">type</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/vscode/" rel="tag">vscode</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E8%BF%90%E7%BB%B4/" rel="tag">运维</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="/tags/3D/" style="font-size: 10px;">3D</a> <a href="/tags/AI/" style="font-size: 11.67px;">AI</a> <a href="/tags/C/" style="font-size: 15px;">C++</a> <a href="/tags/Game/" style="font-size: 18.33px;">Game</a> <a href="/tags/Go/" style="font-size: 13.33px;">Go</a> <a href="/tags/Linux/" style="font-size: 13.33px;">Linux</a> <a href="/tags/Math/" style="font-size: 11.67px;">Math</a> <a href="/tags/Server/" style="font-size: 16.67px;">Server</a> <a href="/tags/Unreal-Engine4/" style="font-size: 10px;">Unreal Engine4</a> <a href="/tags/git/" style="font-size: 10px;">git</a> <a href="/tags/golang/" style="font-size: 20px;">golang</a> <a href="/tags/guitar/" style="font-size: 10px;">guitar</a> <a href="/tags/node-js/" style="font-size: 10px;">node.js</a> <a href="/tags/protobuf/" style="font-size: 10px;">protobuf</a> <a href="/tags/python/" style="font-size: 10px;">python</a> <a href="/tags/recast/" style="font-size: 11.67px;">recast</a> <a href="/tags/redis/" style="font-size: 10px;">redis</a> <a href="/tags/type/" style="font-size: 10px;">type</a> <a href="/tags/vscode/" style="font-size: 10px;">vscode</a> <a href="/tags/%E8%BF%90%E7%BB%B4/" style="font-size: 16.67px;">运维</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/07/">July 2021</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/2021/07/28/2021/2021-07-19-etcd-learn/">go-etcd阅读笔记</a>
          </li>
        
          <li>
            <a href="/2021/07/28/2021/2021-06-22-go-ethereum-learn/">go-ethereum阅读笔记</a>
          </li>
        
          <li>
            <a href="/2021/07/28/2021/2021-06-21-server%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/">server测试工具</a>
          </li>
        
          <li>
            <a href="/2021/07/28/2021/2021-06-09-pprof-doc/">go-pprof</a>
          </li>
        
          <li>
            <a href="/2021/07/28/2021/2021-04-19-c++-metaprogramming/">c++metaprogramming</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2021 Abel Sean<br>
      Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>
    </div>
    <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">Home</a>
  
    <a href="/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>


  
<link rel="stylesheet" href="/fancybox/jquery.fancybox.css">

  
<script src="/fancybox/jquery.fancybox.pack.js"></script>




<script src="/js/script.js"></script>




  </div>
</body>
</html>